package com.ynet.middleground.mobile.approve.mq.consumer;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.ynet.core.common.ServiceResult;
import com.ynet.core.exception.BusinessException;
import com.ynet.core.log.IfpLogger;
import com.ynet.middleground.approve.constant.OperatingTypeEnum;
import com.ynet.middleground.mobile.approve.entity.TaskOperateStage;
import com.ynet.middleground.mobile.approve.mq.SourceMobileApprove;
import com.ynet.middleground.mobile.approve.service.ApproveCenterService;
import com.ynet.middleground.mobile.approve.service.ReceiveOperateMqLogService;
import com.ynet.middleground.mobile.approve.service.TaskOperateStageService;
import com.ynet.middleground.mobile.approve.utils.EnumUtil;

/**
 * 项目名：ifp-mobile-approve <br>
 * 包名：com.ynet.middleground.mobile.approve.mq.consumer <br>
 * 类名：ChannelApproveStateConsumer <br>
 * 描述： 接收渠道端的审批处理结果，再真正调用审批中心对应处理服务
 *
 * @author Suremotoo
 * @create 2021-03-25 23:57
 */
@Component
public class ChannelApproveStateFeedbackConsumer {

    @Autowired
    private TaskOperateStageService taskOperateStageService;

    @Autowired
    private ApproveCenterService approveCenterService;

    @Autowired
    private ReceiveOperateMqLogService receiveOperateMqLogService;

    /**
     * 渠道端通过本消息将审批执行前操作判断结果推送给移动审批 <br>
     * （核心系统主动推送指令结果，这里指需要长时间处理的指令或需要告知审批人指令执行结果的情况）
     *
     * @param msgMap 渠道端对审批处理的结果
     */
    @StreamListener(SourceMobileApprove.BLXD_TO_JKZTYDSP_QDSPJGXX)
    @Transactional(rollbackFor = Exception.class)
    public void inputApproveStateConsumer(Map<String, Object> msgMap) {
        IfpLogger.info("mq", "MQ 渠道端审批处理结果数据，从 Binding-{}收到信息-{}", SourceMobileApprove.BLXD_TO_JKZTYDSP_QDSPJGXX,
            msgMap);
        // 必填参数校验
        Object throwEx = null;
        try {
            throwEx =
                Optional.ofNullable(msgMap).orElseThrow(() -> new BusinessException("渠道审批结果推送数据不能为空", "ECMA0001"));
            throwEx = Optional.ofNullable(msgMap.get("traceId"))
                .orElseThrow(() -> new BusinessException("业务流水 traceId 不能为空", "ECMA0001"));
            throwEx = Optional.ofNullable(msgMap.get("prevTraceId"))
                .orElseThrow(() -> new BusinessException("审批操作执行前业务流水 prevTraceId 不能为空", "ECMA0001"));
            throwEx = Optional.ofNullable(msgMap.get("requestTime"))
                .orElseThrow(() -> new BusinessException("请求时间 requestTime 不能为空", "ECMA0001"));
            throwEx = Optional.ofNullable(msgMap.get("channel"))
                .orElseThrow(() -> new BusinessException("渠道不能为空", "ECMA0001"));
            throwEx = Optional.ofNullable(msgMap.get("hasCommand"))
                .orElseThrow(() -> new BusinessException("是否有执行指令 hasCommand 不能为空", "ECMA0001"));
            throwEx = Optional.ofNullable(msgMap.get("taskId"))
                .orElseThrow(() -> new BusinessException("任务 id taskId 不能为空", "ECMA0001"));
            throwEx = Optional.ofNullable(msgMap.get("allowApproveOperate"))
                .orElseThrow(() -> new BusinessException("是否允许当前审批操作 allowApproveOperate 不能为空", "ECMA0001"));
        } catch (BusinessException e) {
            IfpLogger.error("mq", "MQ 渠道端审批处理结果数据，消息校验出错！throwEx: {}, e: {}", throwEx, e.getMessage());
            if (msgMap == null) {
                msgMap = new HashMap<>(4);
            }
            msgMap.put("errorMsg", e.getMessage());
            receiveOperateMqLogService.log(msgMap);
            return;
        }
        IfpLogger.info("mq", "MQ 渠道端审批处理结果数据，消息校验结果: {}", throwEx);

        // boolean hasCommand = (Boolean)msgMap.get("hasCommand");
        // Object commandResultObj = msgMap.get("commandResult");
        String taskId = String.valueOf(msgMap.get("taskId"));
        boolean allowApproveOperate = (Boolean)msgMap.get("allowApproveOperate");
        String reason = String.valueOf(msgMap.get("reason"));

        String errorMsg = null;
        // 校验查询任务记录为空
        TaskOperateStage taskOperateStage = taskOperateStageService.getTaskOperateStageByTaskId(taskId);
        IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(), "查询任务处理暂存表记录：{}", taskOperateStage);
        if (taskOperateStage == null) {
            msgMap.put("errorMsg", taskId + "该任务记录为空");
            receiveOperateMqLogService.log(msgMap);
            return;
        }

        if (allowApproveOperate) {
            OperatingTypeEnum operatingTypeEnum = EnumUtil.getEnumObject(OperatingTypeEnum.class,
                e -> e.getCode() == Integer.parseInt(taskOperateStage.getOperateType()), "操作类型参数值错误", "ECMA0001");
            ServiceResult serviceResult = null;

            /**
             * <pre>
             * 1. 先更新操作记录表 
             * 2. 再执行审批中心操作服务 
             * 3. 审批中心操作执行完，由审批中心更新 更新操作记录表 IsCompleted 字段 
             * 4. 审批中心调用移动审批推送消息服务，发送钉钉通知
             * </pre>
             */
            taskOperateStage.setGmtModified(LocalDateTime.now());
            taskOperateStage.setIsAllow(true);
            taskOperateStage.setReason(reason);
            taskOperateStageService.updateById(taskOperateStage);

            switch (operatingTypeEnum) {
                // 同意
                case PASS:
                    if (Boolean.TRUE.equals(taskOperateStage.getIsToBeSigned())) {
                        // 如果查询有待签章，则不调用其他逻辑
                        IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
                            "任务 {} 还有待签章，需后续再次进入任务详情处理", taskId);
                        break;
                    }
                    String nextAssignee =
                        taskOperateStageService.getNextAssigneeByOperateData(taskOperateStage.getBusinessOperateData());
                    serviceResult =
                        approveCenterService.invokeApproveCompleteTask(taskOperateStage, nextAssignee, null);
                    break;
                // 退回至发起人
                case RETURN:
                    // 驳回至发起人
                case REJECT_TO_STARTER_DISAGREE:
                case REJECT_TO_STARTER_MODIFICATION:
                    // 驳回、退回均回到 firstNode 节点
                    // 审批中心执行完成后会调用移动审批触发 钉钉通知
                    serviceResult = approveCenterService.invokeApproveReject(taskOperateStage, operatingTypeEnum);
                    break;

                default:
                    break;
            }
            // 推送 审批执行后通知
            errorMsg =
                approveCenterService.pushApproveAfterMsgQueue(serviceResult, taskOperateStage, operatingTypeEnum);
        } else {
            taskOperateStage.setGmtModified(LocalDateTime.now());
            taskOperateStage.setIsAllow(false);
            taskOperateStage.setReason(reason);
            taskOperateStageService.updateById(taskOperateStage);
        }

        msgMap.put("errorMsg", errorMsg);
        // 记录 MQ 日志
        receiveOperateMqLogService.log(msgMap);
    }

}
